package com.tanchengjin.admin.service.impl;

import com.tanchengjin.admin.model.dao.*;
import com.tanchengjin.admin.exception.SystemException;
import com.tanchengjin.admin.model.pojo.*;
import com.tanchengjin.admin.service.AdminMenuService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 菜单表(AdminMenu) ServiceImpl
 *
 * @author TanChengjin
 * @since 2021-11-15 17:06:56
 */
@Service("adminMenuService")
public class AdminMenuServiceImpl implements AdminMenuService {
    private final static Logger logger = LoggerFactory.getLogger(AdminMenuServiceImpl.class);

    private int sortIncrement = 100;
    @Autowired
    private AdminMenuMapper adminMenuMapper;

    @Autowired
    private AdminPermissionMapper adminPermissionMapper;

    @Autowired
    private AdminPermissionMenuMapper adminPermissionMenuMapper;

    @Autowired
    private AdminUserMapper adminUserMapper;

    @Autowired
    private AdminRolePermissionMapper adminRolePermissionMapper;


    public AdminMenu findById(int id) {
        AdminMenu adminMenu = adminMenuMapper.selectByPrimaryKey(id);
        return adminMenu;
    }

    @Override
    public int deleteById(int id) {
        int i = adminMenuMapper.deleteByPrimaryKey(id);
        return i;

    }

    @Transactional
    @Override
    public int insert(AdminMenu adminMenu) {
        //添加时自动增加到当前节点菜单的顶部,使用最大排序值
        int maxSort = adminMenuMapper.getMaxSortByParentId(adminMenu.getParentId());
        adminMenu.setSort(sortIncrement + maxSort);
        int[] permissionList = adminMenu.getPermissionList();
        int i = adminMenuMapper.insertSelective(adminMenu);
        //client 添加了 permission
        int permissionMenu = createPermissionMenu(permissionList, adminMenu.getId());
        return i;
    }

    @Override
    public int updateById(AdminMenu adminMenu, int id) {
        //对0特殊处理
        adminMenu.setId(id);
        Integer parentId = adminMenu.getParentId();
        if (parentId != null && parentId == 0) {
            adminMenu.setParentId(null);
        }
        int i = adminMenuMapper.updateByPrimaryKeySelectiveAllowParentEqualsNull(adminMenu);

        //清空原来菜单的所有权限
        int[] permissionList = adminMenu.getPermissionList();
        int i1 = adminPermissionMenuMapper.deleteByMenuId(id);
        //新增
        createPermissionMenu(permissionList, id);
        return i;
    }


    /**
     * admin_permission_menu表中创建某一菜单的所有权限
     *
     * @param permissionList list
     * @param menuId         id
     * @return int
     */
    private int createPermissionMenu(int[] permissionList, int menuId) {
        int i = 0;
        if (permissionList == null) return i;
        if (permissionList.length >= 1) {
            for (int permissionId : permissionList) {
                AdminPermission adminPermission = adminPermissionMapper.selectByPrimaryKey(permissionId);
                if (adminPermission != null) {
                    AdminPermissionMenu adminPermissionMenu = new AdminPermissionMenu();
                    adminPermissionMenu.setAdminMenuId(menuId);
                    adminPermissionMenu.setAdminPermissionId(adminPermission.getId());
                    i += adminPermissionMenuMapper.insertSelective(adminPermissionMenu);
                }
            }
        }
        return i;
    }

    @Override
    public List<AdminMenu> getAll() {
        List<AdminMenu> adminMenuList = adminMenuMapper.getAll();
        return adminMenuList;
    }


    public int batchDelete(int[] ids) {
        int i = 0;
        for (int id : ids) {
            i += adminMenuMapper.deleteByPrimaryKey(id);
        }
        return i;
    }

    public long count() {
        return adminMenuMapper.count();
    }

    /**
     * 更新排序
     *
     * @param id        所排序ID
     * @param direction 排序
     * @param x         相对于目标ID
     * @param nodeId    上级ID 当x为0，必须知道所要移动到的节点ID
     * @return
     */
    public int updateSort(int id, SortDirection direction, int x, Integer nodeId) {
        int i = 0;
        AdminMenu adminMenu = adminMenuMapper.selectByPrimaryKey(id);
        if (adminMenu == null) return i;
        //移动到最底部
        if (x == 0) {
            return moveToBottom(adminMenu, nodeId);
        }
        //目标节点是否存在
        AdminMenu adminMenuTarget = adminMenuMapper.selectByPrimaryKey(x);
        if (adminMenuTarget == null) return i;
        //不在同一个节点之中，进行移动
        if (!Objects.equals(adminMenu.getParentId(), adminMenuTarget.getParentId())) {
            if (adminMenuTarget.getParentId() == null) {
                //null特殊处理
                adminMenuMapper.updateParentIdIsNullById(adminMenu.getId());
            } else {
                AdminMenu amTmp = new AdminMenu();
                amTmp.setId(adminMenu.getId());
                amTmp.setParentId(adminMenuTarget.getParentId());
                adminMenuMapper.updateByPrimaryKeySelective(amTmp);
            }
        }
        //获取同级所有节点
        List<AdminMenu> nodeList = new ArrayList<AdminMenu>();
        if (adminMenuTarget.getParentId() != null) {
            nodeList = adminMenuMapper.getAllByParentId(adminMenuTarget.getParentId());
        } else {
            nodeList = adminMenuMapper.getAllByParentIdEqualsNullAndOrderByIdAsc();
        }

        //在集合中去除当前ID
        List<AdminMenu> nodeListTmp = new ArrayList<AdminMenu>();
        for (AdminMenu adminMenu1 : nodeList) {
            if (adminMenu1.getId() != id) {
                nodeListTmp.add(adminMenu1);
            }
        }
        nodeList = nodeListTmp;
        if (nodeList.isEmpty()) return i;


        List<AdminMenu> resultList = new ArrayList<AdminMenu>();
        int sortIncrement = 100;
        int tmpId = 0;
        //排序核心逻辑
        for (int index = 0; index <= nodeList.size() - 1; index++) {
            if (nodeList.get(index).getId() == x) {
                //添加索引当前元素
                AdminMenu tmp = nodeList.get(index);
                if (direction.equals(SortDirection.BEFORE)) {
                    resultList.add(adminMenu);
                    resultList.add(tmp);
                } else if (direction.equals(SortDirection.AFTER)) {
                    resultList.add(tmp);
                    resultList.add(adminMenu);
                }

                tmpId = adminMenu.getId();
            } else if ((index + 1 <= nodeList.size() - 1) && (nodeList.get(index + 1).getId() == x)) {
                AdminMenu adminMenuTmp = nodeList.get(index + 1);

                if (direction.equals(SortDirection.BEFORE)) {
                    resultList.add(adminMenu);
                    resultList.add(adminMenuTmp);
                } else if (direction.equals(SortDirection.AFTER)) {
                    resultList.add(adminMenuTmp);
                    resultList.add(adminMenu);
                }
                tmpId = adminMenu.getId();
            } else {
                if (tmpId != x) {
                    //添加索引当前元素
                    AdminMenu tmp = nodeList.get(index);
                    resultList.add(tmp);
                }
            }

        }

        //计算sort
        int var1 = resultList.size();
        AdminMenu am = new AdminMenu();
        for (int p = 0; p <= resultList.size() - 1; p++) {
            //后面没有元素直接移动到最底部
            if ((x == 0) && (resultList.get(p).getId() == x)) {
                am = resultList.get(p);
            } else {
                int i1 = (var1) * sortIncrement;
                resultList.get(p).setSort(i1 <= 0 ? 10 : i1);
                --var1;
            }
        }

        //移动到最底部,设置最小排序
        if (am != null) {
            int s = resultList.get(resultList.size() - 1).getSort();
            am.setSort(s - sortIncrement);
            resultList.add(am);
        }
        i += batchUpdate(resultList);
        return i;
    }

    public int updateSort2(int id, SortDirection direction, int x, Integer nodeId) {
        int i = 0;
        //当前节点是否存在
        AdminMenu adminMenu = adminMenuMapper.selectByPrimaryKey(id);
        if (adminMenu == null) return i;
        //判断是否移动到某节点的最底部
        if (x == 0) {
            AdminMenu tmp = new AdminMenu();
            tmp.setId(id);
            //获取当前节点最小值
            int min = adminMenuMapper.getMinSortByParentId(nodeId);
            tmp.setSort(min - 1);
            tmp.setParentId(nodeId);
            return adminMenuMapper.updateByPrimaryKeySelectiveAllowParentEqualsNull(tmp);
        }
        //目标节点是否存在
        AdminMenu adminMenuTarget = adminMenuMapper.selectByPrimaryKey(x);
        if (direction.equals(SortDirection.BEFORE)) {
            AdminMenu tmp = new AdminMenu();
            tmp.setId(id);
            tmp.setSort(adminMenuTarget.getSort() + 1);
            tmp.setParentId(adminMenuTarget.getParentId());
            return adminMenuMapper.updateByPrimaryKeySelectiveAllowParentEqualsNull(tmp);
        }

        return i;
    }

    private int moveToBottom(AdminMenu adminMenu, Integer parent_id) {
        int i = 0;
        List<AdminMenu> adminMenus = new ArrayList<>();

        if (parent_id == null || parent_id == 0) {
            //顶级分类
            adminMenus = adminMenuMapper.getAllByParentIdEqualsNull();
        } else {
            //获取当前节点下的所有节点
            adminMenus = adminMenuMapper.getAllByParentId(parent_id);
        }

        int increment = 100;
        int len = adminMenus.size();
        for (int j = 0; j <= adminMenus.size() - 1; j++) {
            if (Objects.equals(adminMenus.get(j).getId(), adminMenu.getId())) {
                adminMenus.remove(j);
            } else {
                adminMenus.get(j).setSort(len * increment);
                len--;
            }
        }

        //将当前元素移动到底部
        adminMenu.setSort(1);
        adminMenu.setParentId(parent_id == 0 ? null : parent_id);
        adminMenus.add(adminMenu);
        //批量更新
        i += batchUpdate(adminMenus);
        return i;
    }

    public int batchUpdate(List<AdminMenu> adminMenuList) {
        int i = 0;
        //批量更新
        for (AdminMenu adminMenu : adminMenuList) {
            AdminMenu adminMenuTmp = new AdminMenu();
            adminMenuTmp.setId(adminMenu.getId());
            adminMenuTmp.setSort(adminMenu.getSort());
            adminMenuTmp.setParentId(adminMenu.getParentId());
            i += adminMenuMapper.updateByPrimaryKeySelectiveAllowParentEqualsNull(adminMenuTmp);
        }
        return i;
    }

    /**
     * 重置排序值
     *
     * @param parent_id 条件
     * @return int
     */
    @Transactional
    @Deprecated
    public int resetSort(int parent_id) {
        int i = 0;
        //每节点增加值
        int addN = 100;
        if (parent_id == 0) {
            return i;
        }

        List<AdminMenu> adminMenuMapperAllByParentId = adminMenuMapper.getAllByParentIdEqualsNullAndOrderByIdAsc();

        int idx = 1;
        for (AdminMenu node : adminMenuMapperAllByParentId) {
            AdminMenu adminMenu1 = new AdminMenu();
            adminMenu1.setId(node.getId());
            adminMenu1.setSort(idx * addN);
            int i1 = adminMenuMapper.updateByPrimaryKeySelective(adminMenu1);
            idx++;
        }

        return i;
    }

    public enum SortDirection {
        BEFORE, AFTER;
    }

    /**
     * 获取管理当前可用菜单列表
     *
     * @param id id of admin
     * @return list
     */
    public List<AdminMenu> getAllByAdminId(int id) {
        AdminMenu adminMenu = adminMenuMapper.selectByPrimaryKey(id);
        if (adminMenu == null) throw new SystemException("不存在的管理员");
        return null;
    }

    @Override
    @Deprecated
    public List<AdminMenu> getNodeTree() {
        return this.nodeTreeOperator(new ArrayList<AdminMenu>(), 0, 0);
    }


    private List<AdminMenu> nodeTreeOperator(List<AdminMenu> adminMenuList, int parentId, int level) {
        if (parentId == 0) {
            adminMenuList = adminMenuMapper.getAllByParentIdEqualsNullAndOrderBy("sort", "asc");
        }

        for (AdminMenu adminMenu : adminMenuList) {
            adminMenu.setLevel(level);
            List<AdminMenu> allByParentIdAndOrderBy = adminMenuMapper.getAllByParentIdAndOrderBy(adminMenu.getId(), "sort", "asc");
            if ((allByParentIdAndOrderBy != null) && (allByParentIdAndOrderBy.size() >= 1)) {
                int finalLevel = level += 1;
                allByParentIdAndOrderBy.forEach(e -> {
                    e.setLevel(finalLevel);
                });
                adminMenu.setChildren(allByParentIdAndOrderBy);
                this.nodeTreeOperator(allByParentIdAndOrderBy, adminMenu.getId(), level);
            } else {
                level = 0;
            }
        }
        return adminMenuList;
    }

    @Override
    public List<AdminMenu> getSimpleNodeTree() {
        ArrayList<AdminMenu> adminMenus = new ArrayList<>();
        return simpleNodeTreeOperator(adminMenus, 0, new ArrayList<AdminMenu>(), 0);
    }

    private List<AdminMenu> simpleNodeTreeOperator(List<AdminMenu> adminMenuList, int parentId, List<AdminMenu> adminMenuListResult, int level) {
        if (parentId == 0) {
            adminMenuList = adminMenuMapper.getAllByParentIdEqualsNullAndOrderBy("sort", "desc");
        }

        for (AdminMenu adminMenu : adminMenuList) {
            adminMenu.setLevel(level);
            adminMenuListResult.add(adminMenu);
            List<AdminMenu> allByParentIdAndOrderBy = adminMenuMapper.getAllByParentIdAndOrderBy(adminMenu.getId(), "sort", "desc");
            if (allByParentIdAndOrderBy != null && allByParentIdAndOrderBy.size() >= 1) {
                this.simpleNodeTreeOperator(allByParentIdAndOrderBy, adminMenu.getId(), adminMenuListResult, level += 1);
            }

            if (adminMenu.getParentId() == null) {
                level = 0;
            }
        }
        return adminMenuListResult;
    }

    @Override
    public List<AdminMenu> getMenuTreeByAdminId(int id) {
        AdminUser adminUser = adminUserMapper.selectByPrimaryKey(id);
        if (adminUser == null) throw new SystemException("管理员不存在");

        List<AdminMenu> adminMenuList = adminMenuMapper.selectByAdminId(id, "sort", "desc");
        if (adminMenuList.size() == 0) return adminMenuList;
        return getMenuTreeByList(distinct(adminMenuList), null, 0);
//        return distinct(adminMenuList);
    }

    /**
     * 去重
     * 多表查询重复数据去重
     *
     * @param adminMenuList List
     * @return list
     */
    private List<AdminMenu> distinct(List<AdminMenu> adminMenuList) {
        ArrayList<AdminMenu> adminMenus = new ArrayList<>();

        ArrayList<Integer> ids = new ArrayList<>();

        for (AdminMenu adminMenu : adminMenuList) {
            if (ids.size() >= 1) {
                boolean contains = ids.contains(adminMenu.getId());
                if (contains) continue;
            }
            adminMenus.add(adminMenu);
            ids.add(adminMenu.getId());
        }
        return adminMenus;
    }

    /**
     * @param adminMenuList       list 原始数据
     * @param adminMenuListResult list 排序之后的数据
     * @return list
     */
    private List<AdminMenu> getMenuTreeByList(List<AdminMenu> adminMenuList, List<AdminMenu> adminMenuListResult, int level) {
        if (adminMenuList == null || adminMenuList.size() <= 0) throw new SystemException("Menu Tree Sort Error");

        if (adminMenuListResult == null || adminMenuListResult.size() <= 0) {
            adminMenuListResult = this.getItemByParentId(adminMenuList, null);
        }

        for (AdminMenu adminMenu : adminMenuListResult) {
            List<AdminMenu> itemByParentId = getItemByParentId(adminMenuList, adminMenu.getId());
            if (itemByParentId.size() >= 1) {
                int finalLevel = level;
                itemByParentId.forEach(e -> {
                    e.setLevel(finalLevel);
                });
                adminMenu.setChildren(itemByParentId);

                this.getMenuTreeByList(adminMenuList, itemByParentId, level += 1);
            }
        }

        return adminMenuListResult;

    }

    private List<AdminMenu> getItemByParentId(List<AdminMenu> adminMenuList, Integer parentId) {
        ArrayList<AdminMenu> adminMenus = new ArrayList<>();
        for (AdminMenu adminMenu : adminMenuList) {
            if ((parentId == null || parentId == 0) && adminMenu.getParentId() == null) {
                adminMenus.add(adminMenu);
            } else {
                if (Objects.equals(adminMenu.getParentId(), parentId)) {
                    adminMenus.add(adminMenu);
                }
            }
        }
        return adminMenus;
    }


    @Override
    public List<AdminMenu> getTree() {
        List<AdminMenu> adminMenuList = new ArrayList<>();
        adminMenuList = this.nodeTreeOperator(new ArrayList<AdminMenu>(), 0, 0);
        return adminMenuList;
    }

    @Override
    public boolean checkRoleHasPermission(int roleId, int menuId) {
        ArrayList<Integer> permission = new ArrayList<>();
        //获取当前角色的所有权限
        List<AdminRolePermission> adminRolePermissions = adminRolePermissionMapper.selectByRoleId(roleId);
        adminRolePermissions.forEach(e -> {
            permission.add(e.getAdminPermissionId());
        });

        //通过权限查找相应的菜单
        List<AdminPermissionMenu> adminPermissionMenus = adminPermissionMenuMapper.selectByPermissionIds(permission);

        for (AdminPermissionMenu adminPermissionMenu : adminPermissionMenus) {
            if (adminPermissionMenu.getAdminMenuId() == menuId) return true;
        }

        return false;
    }
}
